home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / other / dopus412-gpl / dopus_disk / diskcopy.c < prev    next >
C/C++ Source or Header  |  2000-02-28  |  20KB  |  762 lines

  1. /*
  2.  
  3. Directory Opus 4
  4. Original GPL release version 4.12
  5. Copyright 1993-2000 Jonathan Potter
  6.  
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. All users of Directory Opus 4 (including versions distributed
  22. under the GPL) are entitled to upgrade to the latest version of
  23. Directory Opus version 5 at a reduced price. Please see
  24. http://www.gpsoft.com.au for more information.
  25.  
  26. The release of Directory Opus 4 under the GPL in NO WAY affects
  27. the existing commercial status of Directory Opus 5.
  28.  
  29. */
  30.  
  31. #include "diskop.h"
  32.  
  33. enum {
  34.     DISKCOPY_VERIFY,
  35.     DISKCOPY_BUMPNAMES,
  36.     DISKCOPY_DISKCOPY,
  37.     DISKCOPY_CANCEL,
  38.     DISKCOPY_CHECK};
  39.  
  40. struct TagItem
  41.     diskcopy_source_list[]={
  42.         {RO_Type,OBJECT_LISTVIEW},
  43.         {RO_ListViewID,0},
  44.         {RO_Top,1},
  45.         {RO_LeftFine,2},
  46.         {RO_Width,10},
  47.         {RO_Height,6},
  48.         {RO_HeightFine,30},
  49.         {RO_TextNum,STR_DISKCOPY_FROM},
  50.         {RO_TextPos,TEXTPOS_ABOVE},
  51.         {RO_HighRecess,TRUE},
  52.         {TAG_END,0}},
  53.     diskcopy_destination_list[]={
  54.         {RO_Type,OBJECT_LISTVIEW},
  55.         {RO_ListViewID,1},
  56.         {RO_Top,1},
  57.         {RO_Left,33},
  58.         {RO_LeftFine,-18},
  59.         {RO_Width,10},
  60.         {RO_Height,6},
  61.         {RO_HeightFine,30},
  62.         {RO_TextNum,STR_DISKCOPY_TO},
  63.         {RO_TextPos,TEXTPOS_ABOVE},
  64.         {RO_HighRecess,TRUE},
  65.         {TAG_END,0}},
  66.  
  67.     diskcopy_verify_gadget[]={
  68.         {RO_Type,OBJECT_GADGET},
  69.         {RO_GadgetType,GADGET_CHECK},
  70.         {RO_GadgetID,DISKCOPY_VERIFY},
  71.         {RO_Left,14},
  72.         {RO_Top,4},
  73.         {RO_TextNum,STR_FORMAT_VERIFY},
  74.         {RO_TextPos,TEXTPOS_RIGHT},
  75.         {RO_LeftFine,-2},
  76.         {RO_BoolOn,TRUE},
  77.         {TAG_END,0}},
  78.  
  79.     diskcopy_bumpnames_gadget[]={
  80.         {RO_Type,OBJECT_GADGET},
  81.         {RO_GadgetType,GADGET_CHECK},
  82.         {RO_GadgetID,DISKCOPY_BUMPNAMES},
  83.         {RO_Left,14},
  84.         {RO_Top,6},
  85.         {RO_TextNum,STR_BUMP_NAMES},
  86.         {RO_TextPos,TEXTPOS_RIGHT},
  87.         {RO_LeftFine,-2},
  88.         {RO_BoolOn,TRUE},
  89.         {TAG_END,0}},
  90.  
  91.     diskcopy_info_box[]={
  92.         {RO_Type,OBJECT_BORDER},
  93.         {RO_BorderType,BORDER_RECESSED},
  94.         {RO_LeftFine,2},
  95.         {RO_Top,7},
  96.         {RO_TopFine,36},
  97.         {RO_Width,43},
  98.         {RO_WidthFine,-4},
  99.         {RO_Height,1},
  100.         {RO_HeightFine,4},
  101.         {TAG_END,0}},
  102.  
  103.     diskcopy_diskcopy_gadget[]={
  104.         {RO_Type,OBJECT_GADGET},
  105.         {RO_GadgetType,GADGET_BOOLEAN},
  106.         {RO_GadgetID,DISKCOPY_DISKCOPY},
  107.         {RO_Top,8},
  108.         {RO_TopFine,45},
  109.         {RO_Width,13},
  110.         {RO_Height,1},
  111.         {RO_HeightFine,4},
  112.         {RO_TextNum,STR_DISKCOPY_DISKCOPY},
  113.         {RO_TextPos,TEXTPOS_CENTER},
  114.         {RO_HighRecess,TRUE},
  115.         {TAG_END,0}},
  116.  
  117.     diskcopy_check_gadget[]={
  118.         {RO_Type,OBJECT_GADGET},
  119.         {RO_GadgetType,GADGET_BOOLEAN},
  120.         {RO_GadgetID,DISKCOPY_CHECK},
  121.         {RO_Left,15},
  122.         {RO_Top,8},
  123.         {RO_TopFine,45},
  124.         {RO_Width,13},
  125.         {RO_Height,1},
  126.         {RO_HeightFine,4},
  127.         {RO_TextNum,STR_DISKCOPY_CHECK},
  128.         {RO_TextPos,TEXTPOS_CENTER},
  129.         {RO_HighRecess,TRUE},
  130.         {TAG_END,0}},
  131.  
  132.     diskcopy_cancel_gadget[]={
  133.         {RO_Type,OBJECT_GADGET},
  134.         {RO_GadgetType,GADGET_BOOLEAN},
  135.         {RO_GadgetID,DISKCOPY_CANCEL},
  136.         {RO_Left,30},
  137.         {RO_Top,8},
  138.         {RO_TopFine,45},
  139.         {RO_Width,13},
  140.         {RO_Height,1},
  141.         {RO_HeightFine,4},
  142.         {RO_TextNum,STR_FORMAT_EXIT},
  143.         {RO_TextPos,TEXTPOS_CENTER},
  144.         {RO_HighRecess,TRUE},
  145.         {TAG_END,0}},
  146.  
  147.     *diskcopy_gadgets[]={
  148.         diskcopy_verify_gadget,
  149.         diskcopy_bumpnames_gadget,
  150.         diskcopy_diskcopy_gadget,
  151.         diskcopy_check_gadget,
  152.         diskcopy_cancel_gadget,
  153.         NULL};
  154.  
  155. void diskop_diskcopy(vis,portname,argc,argv)
  156. struct VisInfo *vis;
  157. char *portname;
  158. int argc;
  159. char *argv[];
  160. {
  161.     struct RequesterBase diskcopyreq;
  162.     struct Window *window;
  163.     struct IntuiMessage *msg;
  164.     Object_Border *infobox;
  165.     struct DOpusListView *sourcelist,*destinationlist,*view;
  166.     struct Gadget *gadlist;
  167.     ULONG class;
  168.     USHORT code,gadgetid;
  169.     APTR iaddress;
  170.     int a,b,gadcount=0,ignorechange=0;
  171.     int source=-1,dest=-1,startverify=0,bumpnames=0,oldsel;
  172.     int startcheck=0;
  173.     struct DOpusRemember *destkey=NULL;
  174.  
  175.     diskcopyreq.rb_width=43;
  176.     diskcopyreq.rb_height=9;
  177.     diskcopyreq.rb_widthfine=16;
  178.     diskcopyreq.rb_heightfine=61;
  179.     diskcopyreq.rb_leftoffset=8;
  180.     diskcopyreq.rb_topoffset=8;
  181.     diskcopyreq.rb_flags=0;
  182.  
  183.     fill_out_req(&diskcopyreq,vis);
  184.  
  185.     diskcopyreq.rb_privateflags=0;
  186.     diskcopyreq.rb_screenname=NULL;
  187.  
  188.     if (diskcopyreq.rb_screen && !(vis->vi_flags&VISF_BORDERS)) {
  189.         diskcopyreq.rb_flags|=RBF_STRINGS;
  190.         diskcopyreq.rb_title=NULL;
  191.     }
  192.     else {
  193.         diskcopyreq.rb_flags|=RBF_BORDERS|RBF_CLOSEGAD|RBF_STRINGS;
  194.         diskcopyreq.rb_title=string_table[STR_DISKCOPY_DISKCOPY];
  195.     }
  196.  
  197.     diskcopyreq.rb_extend=NULL;
  198.     diskcopyreq.rb_idcmpflags=0;
  199.     diskcopyreq.rb_string_table=string_table;
  200.  
  201.     if (!(window=OpenRequester(&diskcopyreq)) ||
  202.         !(gadlist=addreqgadgets(&diskcopyreq,diskcopy_gadgets,0,&gadcount)) ||
  203.         !(infobox=(Object_Border *)
  204.             AddRequesterObject(&diskcopyreq,diskcopy_info_box)) ||
  205.         !(sourcelist=(struct DOpusListView *)
  206.             AddRequesterObject(&diskcopyreq,diskcopy_source_list)) ||
  207.         !(sourcelist->items=get_device_list(&diskcopyreq.rb_memory,NULL)) ||
  208.         !(destinationlist=(struct DOpusListView *)
  209.             AddRequesterObject(&diskcopyreq,diskcopy_destination_list))) {
  210.         CloseRequester(&diskcopyreq);
  211.         return;
  212.     }
  213.  
  214.     fix_listview(&diskcopyreq,sourcelist);
  215.     fix_listview(&diskcopyreq,destinationlist);
  216.  
  217.     select_device(sourcelist,NULL);
  218.     get_env("diskcopy",gadlist,gadcount,sourcelist);
  219.  
  220.     oldsel=sourcelist->itemselected;
  221.  
  222.     for (a=0;a<argc;a++) {
  223.         if (LStrCmpI(argv[a],"verify")==0) startverify=1;
  224.         else if (LStrnCmpI(argv[a],"bump",4)==0) bumpnames=1;
  225.         else if (LStrnCmpI(argv[a],"check",5)==0) startcheck=1;
  226.         else {
  227.             if (source==-1) {
  228.                 for (b=0;sourcelist->items[b];b++) {
  229.                     if (LStrCmpI(argv[a],sourcelist->items[b])==0) {
  230.                         source=b;
  231.                         sourcelist->itemselected=b;
  232.                         destinationlist->items=
  233.                             get_device_list(&destkey,sourcelist->items[b]);
  234.                         break;
  235.                     }
  236.                 }
  237.             }
  238.             else if (dest==-1 && destinationlist->items) {
  239.                 for (b=0;destinationlist->items[b];b++) {
  240.                     if (LStrCmpI(argv[a],destinationlist->items[b])==0) {
  241.                         dest=b;
  242.                         destinationlist->itemselected=b;
  243.                         break;
  244.                     }
  245.                 }
  246.             }
  247.         }
  248.     }
  249.  
  250.     if (source>-1 && dest==-1) {
  251.         LFreeRemember(&destkey);
  252.         destinationlist->items=NULL;
  253.         sourcelist->itemselected=oldsel;
  254.         startverify=bumpnames=0;
  255.     }
  256.  
  257.     if (!destinationlist->items) {
  258.         destinationlist->items=
  259.             get_device_list(&destkey,sourcelist->items[sourcelist->itemselected]);
  260.         select_device(destinationlist,sourcelist->items[sourcelist->itemselected]);
  261.         sourcelist->next=destinationlist;
  262.         if (source==-1) get_env("diskcopy",gadlist,gadcount,sourcelist);
  263.     }
  264.     else sourcelist->next=destinationlist;
  265.  
  266.     if (!(AddListView(sourcelist,2))) {
  267.         CloseRequester(&diskcopyreq);
  268.         LFreeRemember(&destkey);
  269.         return;
  270.     }
  271.     show_sel_item(sourcelist);
  272.  
  273.     if (startverify) gadlist->Flags|=GFLG_SELECTED;
  274.     else if (dest>-1) gadlist->Flags&=~GFLG_SELECTED;
  275.  
  276.     if (bumpnames) gadlist->NextGadget->Flags|=GFLG_SELECTED;
  277.     else if (dest>-1) gadlist->NextGadget->Flags&=~GFLG_SELECTED;
  278.  
  279.     RefreshRequesterObject(&diskcopyreq,NULL);
  280.     RefreshGList(gadlist,window,NULL,gadcount);
  281.     show_diskcopy_info(&diskcopyreq,infobox,sourcelist->items[sourcelist->itemselected]);
  282.  
  283.     if (dest>-1) {
  284.         if (do_diskcopy(&diskcopyreq,
  285.             infobox,
  286.             sourcelist->items[sourcelist->itemselected],
  287.             destinationlist->items[destinationlist->itemselected],
  288.             (gadlist->Flags&GFLG_SELECTED),
  289.             (gadlist->NextGadget->Flags&GFLG_SELECTED),
  290.             startcheck)) {
  291.             dopus_message(DOPUSMSG_UPDATEDRIVE,
  292.                 (APTR)destinationlist->items[destinationlist->itemselected],
  293.                 portname);
  294.         }
  295.         RemoveListView(sourcelist,2);
  296.         CloseRequester(&diskcopyreq);
  297.         LFreeRemember(&destkey);
  298.         return;
  299.     }
  300.  
  301.     FOREVER {
  302.         while (msg=(struct IntuiMessage *)GetMsg(window->UserPort)) {
  303.             if ((view=(struct DOpusListView *)ListViewIDCMP(sourcelist,msg))==
  304.                 (struct DOpusListView *)-1) {
  305.                 class=msg->Class; code=msg->Code;
  306.                 iaddress=msg->IAddress;
  307.                 ReplyMsg((struct Message *)msg);
  308.  
  309.                 switch (class) {
  310.                     case IDCMP_DISKINSERTED:
  311.                     case IDCMP_DISKREMOVED:
  312.                         if (ignorechange) ignorechange=0;
  313.                         else {
  314.                             show_diskcopy_info(&diskcopyreq,
  315.                                 infobox,
  316.                                 sourcelist->items[sourcelist->itemselected]);
  317.                         }
  318.                         break;
  319.  
  320.                     case IDCMP_VANILLAKEY:    
  321.                         code=toupper(code);
  322.                         switch (code) {
  323.                             case 'V':
  324.                                 gadlist->Flags^=GFLG_SELECTED;
  325.                                 RefreshGList(gadlist,window,NULL,1);
  326.                                 break;
  327.                             case 'B':
  328.                                 gadlist->NextGadget->Flags^=GFLG_SELECTED;
  329.                                 RefreshGList(gadlist,window,NULL,1);
  330.                                 break;
  331.                             case 0x1b:
  332.                                 set_env("diskcopy",gadlist,gadcount,sourcelist);
  333.                                 RemoveListView(sourcelist,2);
  334.                                 CloseRequester(&diskcopyreq);
  335.                                 LFreeRemember(&destkey);
  336.                                 return;
  337.                         }
  338.                         break;
  339.  
  340.                     case IDCMP_GADGETDOWN:
  341.                     case IDCMP_GADGETUP:
  342.                         gadgetid=((struct Gadget *)iaddress)->GadgetID;
  343.                     case IDCMP_CLOSEWINDOW:
  344.                         if (class==IDCMP_CLOSEWINDOW) gadgetid=DISKCOPY_CANCEL;
  345.  
  346.                         switch (gadgetid) {
  347.                             case DISKCOPY_CANCEL:
  348.                                 set_env("diskcopy",gadlist,gadcount,sourcelist);
  349.                                 RemoveListView(sourcelist,2);
  350.                                 CloseRequester(&diskcopyreq);
  351.                                 LFreeRemember(&destkey);
  352.                                 return;
  353.                             case DISKCOPY_DISKCOPY:
  354.                             case DISKCOPY_CHECK:
  355.                                 if (do_diskcopy(&diskcopyreq,
  356.                                     infobox,
  357.                                     sourcelist->items[sourcelist->itemselected],
  358.                                     destinationlist->items[destinationlist->itemselected],
  359.                                     (gadlist->Flags&GFLG_SELECTED),
  360.                                     (gadlist->NextGadget->Flags&GFLG_SELECTED),
  361.                                     (gadgetid==DISKCOPY_CHECK))) {
  362.                                     ignorechange=1;
  363.                                     dopus_message(DOPUSMSG_UPDATEDRIVE,
  364.                                         (APTR)destinationlist->items[destinationlist->itemselected],
  365.                                         portname);
  366.                                 }
  367.                                 break;
  368.                         }
  369.                         break;
  370.                 }
  371.             }
  372.             else if (view) {
  373.                 switch (view->listid) {
  374.                     case 0:
  375.                         LFreeRemember(&destkey);
  376.                         destinationlist->items=get_device_list(&destkey,view->items[view->itemselected]);
  377.                         select_device(destinationlist,view->items[view->itemselected]);
  378.                         RefreshListView(destinationlist,1);
  379.                         show_diskcopy_info(&diskcopyreq,infobox,sourcelist->items[sourcelist->itemselected]);
  380.                         break;
  381.                 }
  382.             }
  383.         }
  384.         Wait(1<<window->UserPort->mp_SigBit);
  385.     }
  386. }
  387.  
  388. void show_diskcopy_info(reqbase,border,name)
  389. struct RequesterBase *reqbase;
  390. Object_Border *border;
  391. char *name;
  392. {
  393.     char infobuf[60],sizebuf[20];
  394.     BPTR lock;
  395.     struct FileInfoBlock __aligned fib;
  396.     struct InfoData __aligned info;
  397.     struct Process *myproc;
  398.     APTR wsave;
  399.  
  400.     myproc=(struct Process *)FindTask(NULL);
  401.     wsave=myproc->pr_WindowPtr;
  402.     myproc->pr_WindowPtr=(APTR)-1;
  403.  
  404.     border_text(reqbase,border,NULL);
  405.  
  406.     if (name) {
  407.         if (lock=Lock(name,ACCESS_READ)) {
  408.             Info(lock,&info);
  409.             Examine(lock,&fib);
  410.             UnLock(lock);
  411.  
  412.             getsizestring(sizebuf,info.id_NumBlocksUsed*info.id_BytesPerBlock);
  413.             lsprintf(infobuf,string_table[STR_DISKCOPY_INFODISPLAY],fib.fib_FileName,sizebuf);
  414.  
  415.             border_text(reqbase,border,infobuf);
  416.         }
  417.         else border_text(reqbase,border,string_table[STR_DISKCOPY_NODISK]);
  418.     }
  419.     myproc->pr_WindowPtr=wsave;
  420. }
  421.  
  422. do_diskcopy(reqbase,border,source,dest,verify,bump,check)
  423. struct RequesterBase *reqbase;
  424. Object_Border *border;
  425. char *source,*dest;
  426. int verify,bump,check;
  427. {
  428.     struct IOExtTD *device_req[2];
  429.     struct MsgPort *device_port[2];
  430.     struct DeviceNode *source_node,*dest_node;
  431.     struct FileSysStartupMsg *startup;
  432.     struct DosEnvec *dosenvec;
  433.     struct Requester busyreq;
  434.     ULONG tracksize,lowtrack[2],numtracks,memtype,deviceunit[2],deviceflags[2],track;
  435.     ULONG trackcount,trackmod,curtrack,offset;
  436.     char devicename[2][40],infobuf[80];
  437.     int a,b,drives,abort=0,err=0,cmpsize,txt=-1;
  438.     char *buffer=NULL,*dev_table[2];
  439.     ULONG *verifybuffer=NULL,*cmpbuffer;
  440.     struct DOpusRemember *memkey=NULL;
  441.  
  442.     if (!source || !dest ||
  443.         !(source_node=find_device(source)) ||
  444.         !(dest_node=find_device(dest))) return(0);
  445.  
  446.     if (check) verify=1;
  447.     if (LStrCmpI(source,dest)==0) drives=1;
  448.     else drives=2;
  449.  
  450.     dev_table[0]=source; dev_table[1]=dest;
  451.  
  452.     for (a=0;a<2;a++) {
  453.         device_port[a]=NULL;
  454.         device_req[a]=NULL;
  455.     }
  456.  
  457.     startup=(struct FileSysStartupMsg *)BADDR(source_node->dn_Startup);
  458.     BtoCStr((BPTR)startup->fssm_Device,devicename[0],40);
  459.     deviceunit[0]=startup->fssm_Unit;
  460.     deviceflags[0]=startup->fssm_Flags;
  461.  
  462.     dosenvec=(struct DosEnvec *)BADDR(startup->fssm_Environ);
  463.     tracksize=(dosenvec->de_SizeBlock<<2)*dosenvec->de_Surfaces*dosenvec->de_BlocksPerTrack;
  464.     lowtrack[0]=dosenvec->de_LowCyl;
  465.     numtracks=dosenvec->de_HighCyl-dosenvec->de_LowCyl+1;
  466.     memtype=dosenvec->de_BufMemType;
  467.  
  468.     Forbid();
  469.  
  470.     if (drives==2) trackcount=1;
  471.     else {
  472.         if ((trackcount=AvailMem(memtype|MEMF_LARGEST)/tracksize)>1) {
  473.             if (numtracks%trackcount) {
  474.                 trackmod=(numtracks/trackcount)+1;
  475.                 trackcount=numtracks/trackmod;
  476.             }
  477.         }
  478.     }
  479.  
  480.     if (trackcount>0) buffer=LAllocRemember(&memkey,tracksize*trackcount,memtype);
  481.  
  482.     Permit();
  483.  
  484.     if (!buffer) {
  485.         border_text(reqbase,border,string_table[STR_MEMORY_ERROR]);
  486.         return(0);
  487.     }
  488.  
  489.     cmpbuffer=(ULONG *)buffer;
  490.  
  491.     if (verify) {
  492.         verifybuffer=(ULONG *)LAllocRemember(&memkey,tracksize,memtype);
  493.         cmpsize=tracksize>>2;
  494.     }
  495.     if (check && !verifybuffer) {
  496.         border_text(reqbase,border,string_table[STR_MEMORY_ERROR]);
  497.         return(0);
  498.     }
  499.  
  500.     startup=(struct FileSysStartupMsg *)BADDR(dest_node->dn_Startup);
  501.     BtoCStr((BPTR)startup->fssm_Device,devicename[1],40);
  502.     deviceunit[1]=startup->fssm_Unit;
  503.     deviceflags[1]=startup->fssm_Flags;
  504.  
  505.     dosenvec=(struct DosEnvec *)BADDR(startup->fssm_Environ);
  506.     lowtrack[1]=dosenvec->de_LowCyl;
  507.  
  508.     for (a=0;a<2;a++) {
  509.         if (!(device_port[a]=LCreatePort(NULL,0)) ||
  510.             !(device_req[a]=(struct IOExtTD *)
  511.             LCreateExtIO(device_port[a],sizeof(struct IOExtTD)))) break;
  512.         if (OpenDevice(devicename[a],deviceunit[a],
  513.             (struct IORequest *)device_req[a],deviceflags[a])) {
  514.             LDeleteExtIO((struct IORequest *)device_req[a]);
  515.             device_req[a]=NULL;
  516.             break;
  517.         }
  518.     }
  519.  
  520.     if (a==2) {
  521.         InitRequester(&busyreq);
  522.         busyreq.Flags=NOISYREQ;
  523.         Request(&busyreq,reqbase->rb_window);
  524.         SetBusyPointer(reqbase->rb_window);
  525.  
  526.         if (drives==2) {
  527.             border_text(reqbase,border,string_table[STR_CHECKING_DISKS]);
  528.  
  529.             for (a=0;a<2;a++) {
  530.                 if (!(check_disk(reqbase,device_req[a],dev_table[a],(check)?0:a))) break;
  531.                 if (a==1 && !check && !(check_blank_disk(reqbase,dev_table[a],
  532.                     string_table[STR_DISKCOPY_DISKCOPY])))
  533.                     break;
  534.             }
  535.         }
  536.         else a=2;
  537.  
  538.         if (a==2) {
  539.             inhibit_drive(source,DOSTRUE);
  540.             if (drives==2) inhibit_drive(dest,DOSTRUE);
  541.  
  542.             for (a=0;a<drives;a++) drive_motor(device_req[a],1);
  543.  
  544.             for (track=0;track<numtracks;track+=trackcount) {
  545.  
  546.                 offset=(lowtrack[0]+track)*tracksize;
  547.  
  548.                 if (drives==1) {
  549.                     lsprintf(infobuf,string_table[STR_DISKCOPY_INSERTSOURCE],source);
  550.                     border_text(reqbase,border,infobuf);
  551.                     drive_motor(device_req[0],0);
  552.                     if (!(check_error(reqbase,infobuf,STR_PROCEED)) ||
  553.                         !(check_disk(reqbase,device_req[0],source,0))) {
  554.                         err=ERROR_ABORTED;
  555.                         break;
  556.                     }
  557.                     drive_motor(device_req[0],1);
  558.                 }
  559.  
  560.                 for (curtrack=0;curtrack<trackcount;curtrack++) {
  561.  
  562.                     lsprintf(infobuf,string_table[STR_DISKCOPY_READING],
  563.                         track+curtrack,numtracks-curtrack-track-1);
  564.                     border_text(reqbase,border,infobuf);
  565.  
  566.                     if (check_abort(reqbase->rb_window)) {
  567.                         abort=1;
  568.                         err=ERROR_ABORTED;
  569.                         break;
  570.                     }
  571.  
  572.                     FOREVER {
  573.                         device_req[0]->iotd_Req.io_Command=CMD_READ;
  574.                         device_req[0]->iotd_Req.io_Data=(APTR)&buffer[curtrack*tracksize];
  575.                         device_req[0]->iotd_Req.io_Offset=offset;
  576.                         device_req[0]->iotd_Req.io_Length=tracksize;
  577.  
  578.                         if (!(DoIO((struct IORequest *)device_req[0]))) break;
  579.  
  580.                         lsprintf(infobuf,string_table[STR_DISKCOPY_READERROR],track+curtrack);
  581.                         border_text(reqbase,border,infobuf);
  582.                         if (!(check_error(reqbase,infobuf,STR_RETRY))) {
  583.                             abort=1;
  584.                             err=ERROR_FAILED;
  585.                             break;
  586.                         }
  587.                     }
  588.  
  589.                     if (abort) break;
  590.                     offset+=tracksize;
  591.                 }
  592.  
  593.                 if (abort) break;
  594.  
  595.                 offset=(lowtrack[1]+track)*tracksize;
  596.  
  597.                 if (drives==1) {
  598.                     lsprintf(infobuf,string_table[STR_DISKCOPY_INSERTDEST],dest);
  599.                     border_text(reqbase,border,infobuf);
  600.                     drive_motor(device_req[0],0);
  601.                     if (!(check_error(reqbase,infobuf,STR_PROCEED)) ||
  602.                         !(check_disk(reqbase,device_req[1],dest,1))) {
  603.                         err=ERROR_ABORTED;
  604.                         abort=1;
  605.                         break;
  606.                     }
  607.                     drive_motor(device_req[0],1);
  608.                 }
  609.  
  610.                 for (curtrack=0;curtrack<trackcount;curtrack++) {
  611.  
  612.                     if (!check) {
  613.                         lsprintf(infobuf,string_table[STR_DISKCOPY_WRITING],
  614.                             track+curtrack,numtracks-curtrack-track-1);
  615.                         border_text(reqbase,border,infobuf);
  616.  
  617.                         if (check_abort(reqbase->rb_window)) {
  618.                             abort=1;
  619.                             err=ERROR_ABORTED;
  620.                             break;
  621.                         }
  622.  
  623.                         FOREVER {
  624.                             device_req[1]->iotd_Req.io_Command=TD_FORMAT;
  625.                             device_req[1]->iotd_Req.io_Data=(APTR)&buffer[curtrack*tracksize];
  626.                             device_req[1]->iotd_Req.io_Offset=offset;
  627.                             device_req[1]->iotd_Req.io_Length=tracksize;
  628.  
  629.                             if (!(DoIO((struct IORequest *)device_req[1]))) {
  630.                                 if (!verifybuffer) break;
  631.                                 device_req[1]->iotd_Req.io_Command=CMD_UPDATE;
  632.                                 if (!(DoIO((struct IORequest *)device_req[1]))) break;
  633.                             }
  634.  
  635.                             lsprintf(infobuf,string_table[STR_DISKCOPY_WRITEERROR],track+curtrack);
  636.                             border_text(reqbase,border,infobuf);
  637.                             if (!(check_error(reqbase,infobuf,STR_RETRY))) {
  638.                                 abort=1;
  639.                                 err=ERROR_FAILED;
  640.                                 break;
  641.                             }
  642.                         }
  643.  
  644.                         if (abort) break;
  645.                     }
  646.  
  647.                     if (verifybuffer) {
  648.                         lsprintf(infobuf,string_table[STR_FORMAT_VERIFYING],
  649.                             track+curtrack,numtracks-curtrack-track-1);
  650.                         border_text(reqbase,border,infobuf);
  651.  
  652.                         FOREVER {
  653.                             device_req[1]->iotd_Req.io_Command=CMD_READ;
  654.                             device_req[1]->iotd_Req.io_Data=(APTR)verifybuffer;
  655.                             device_req[1]->iotd_Req.io_Offset=offset;
  656.                             device_req[1]->iotd_Req.io_Length=tracksize;
  657.  
  658.                             if (!(DoIO((struct IORequest *)device_req[1]))) {
  659.                                 for (a=0,b=curtrack*cmpsize;a<cmpsize;a++,b++) {
  660.                                     if (verifybuffer[a]!=cmpbuffer[b]) break;
  661.                                 }
  662.                                 if (a==cmpsize) break;
  663.                                 lsprintf(infobuf,string_table[STR_FORMAT_VERIFYERROR],track+curtrack);
  664.                                 err=ERROR_VERIFY;
  665.                             }
  666.                             else {
  667.                                 lsprintf(infobuf,string_table[STR_DISKCOPY_READERROR],track+curtrack);
  668.                                 err=ERROR_FAILED;
  669.                             }
  670.  
  671.                             border_text(reqbase,border,infobuf);
  672.                             if (!(check_error(reqbase,infobuf,STR_RETRY))) {
  673.                                 abort=1;
  674.                                 break;
  675.                             }
  676.                             err=0;
  677.                         }
  678.  
  679.                         if (abort) break;
  680.                     }
  681.  
  682.                     offset+=tracksize;
  683.                 }
  684.  
  685.             }
  686.  
  687.             for (a=0;a<drives;a++) drive_motor(device_req[a],0);
  688.  
  689.             switch (err) {
  690.                 case 0:
  691.                     if (bump && !check) {
  692.                         border_text(reqbase,border,string_table[STR_BUMPING_NAME]);
  693.                         inhibit_drive(dest,FALSE);
  694.                         bump_disk_name(dest);
  695.                     }
  696.                     txt=STR_SUCCESS;
  697.                     break;
  698.                 case ERROR_ABORTED: txt=STR_ABORTED; break;
  699.                 case ERROR_FAILED: txt=STR_FAILED_ERROR; break;
  700.                 case ERROR_VERIFY: txt=-1; break;
  701.             }
  702.  
  703.             inhibit_drive(source,FALSE);
  704.             if (drives==2) inhibit_drive(dest,FALSE);
  705.         }
  706.         else txt=STR_ABORTED;
  707.  
  708.         EndRequest(&busyreq,reqbase->rb_window);
  709.         ClearPointer(reqbase->rb_window);
  710.     }
  711.     else txt=STR_NODEVICE_ERROR;
  712.  
  713.     if (txt>-1) border_text(reqbase,border,string_table[txt]);
  714.  
  715.     for (a=0;a<2;a++) {
  716.         if (device_req[a]) {
  717.             CloseDevice((struct IORequest *)device_req[a]);
  718.             LDeleteExtIO((struct IORequest *)device_req[a]);
  719.         }
  720.         if (device_port[a]) LDeletePort(device_port[a]);
  721.     }
  722.  
  723.     LFreeRemember(&memkey);
  724.     return((txt==STR_SUCCESS));
  725. }
  726.  
  727. void bump_disk_name(disk)
  728. char *disk;
  729. {
  730.     if (IconBase) {
  731.         struct Process *myproc;
  732.         APTR wsave;
  733.         BPTR lock;
  734.  
  735.         myproc=(struct Process *)FindTask(NULL);
  736.         wsave=myproc->pr_WindowPtr;
  737.         myproc->pr_WindowPtr=(APTR)-1;
  738.  
  739.         if (lock=Lock(disk,ACCESS_READ)) {
  740.             struct FileInfoBlock __aligned info;
  741.             char namebuf[32];
  742.             struct MsgPort *port;
  743.  
  744.             Examine(lock,&info);
  745.             UnLock(lock);
  746.  
  747.             BumpRevision(namebuf,info.fib_FileName);
  748.  
  749.             if (port=(struct MsgPort *)DeviceProc(disk)) {
  750.                 char __aligned bstr_name[36];
  751.                 ULONG arg;
  752.  
  753.                 bstr_name[0]=strlen(namebuf);
  754.                 strcpy(&bstr_name[1],namebuf);
  755.                 arg=(ULONG)bstr_name>>2;
  756.                 SendPacket(port,ACTION_RENAME_DISK,&arg,1);
  757.             }
  758.         }
  759.         myproc->pr_WindowPtr=wsave;
  760.     }
  761. }
  762.